from flask import Flask, render_template, redirect, url_for, flash, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, EmailField, TextAreaField, SelectField, FileField, DateField, TimeField
from wtforms.validators import InputRequired, Length, Email, EqualTo, ValidationError
from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.utils import secure_filename
import os
from datetime import datetime, timedelta
import secrets

# 应用初始化
app = Flask(__name__)
app.config['SECRET_KEY'] = secrets.token_hex(16)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///campus_assistant.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['UPLOAD_FOLDER'] = 'static/uploads'
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024  # 16MB

# 确保上传文件夹存在
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)

# 数据库初始化
db = SQLAlchemy(app)

# 登录管理器初始化
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'

# 数据模型定义
class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), unique=True, nullable=False)
    email = db.Column(db.String(100), unique=True, nullable=False)
    password = db.Column(db.String(200), nullable=False)
    full_name = db.Column(db.String(100), nullable=True)
    student_id = db.Column(db.String(20), nullable=True)
    department = db.Column(db.String(100), nullable=True)
    major = db.Column(db.String(100), nullable=True)
    grade = db.Column(db.Integer, nullable=True)
    bio = db.Column(db.Text, nullable=True)
    avatar = db.Column(db.String(200), nullable=True, default='default_avatar.png')
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    
    # 关系定义
    courses = db.relationship('Course', backref='user', lazy=True)
    scores = db.relationship('Score', backref='user', lazy=True)
    activities = db.relationship('Activity', backref='organizer', lazy=True)
    resources = db.relationship('Resource', backref='uploader', lazy=True)
    messages_sent = db.relationship('Message', foreign_keys='Message.sender_id', backref='sender', lazy=True)
    messages_received = db.relationship('Message', foreign_keys='Message.receiver_id', backref='receiver', lazy=True)
    activity_participants = db.relationship('ActivityParticipant', backref='user', lazy=True)
    resource_collections = db.relationship('ResourceCollection', backref='user', lazy=True)

class Course(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    course_code = db.Column(db.String(20), nullable=False)
    name = db.Column(db.String(100), nullable=False)
    instructor = db.Column(db.String(100), nullable=True)
    credits = db.Column(db.Float, nullable=True)
    day_of_week = db.Column(db.Integer, nullable=False)  # 0=Monday, 1=Tuesday, etc.
    start_time = db.Column(db.Time, nullable=False)
    end_time = db.Column(db.Time, nullable=False)
    location = db.Column(db.String(100), nullable=True)
    semester = db.Column(db.String(20), nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    
    # 关系定义
    scores = db.relationship('Score', backref='course', lazy=True)

class Score(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    course_id = db.Column(db.Integer, db.ForeignKey('course.id'), nullable=True)
    course_name = db.Column(db.String(100), nullable=False)
    credits = db.Column(db.Float, nullable=False)
    score_value = db.Column(db.Float, nullable=False)
    semester = db.Column(db.String(20), nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

class Activity(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(200), nullable=False)
    description = db.Column(db.Text, nullable=True)
    category = db.Column(db.String(50), nullable=True)
    location = db.Column(db.String(100), nullable=True)
    start_time = db.Column(db.DateTime, nullable=False)
    end_time = db.Column(db.DateTime, nullable=False)
    organizer_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    image = db.Column(db.String(200), nullable=True)
    max_participants = db.Column(db.Integer, nullable=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    
    # 关系定义
    participants = db.relationship('ActivityParticipant', backref='activity', lazy=True)

class Resource(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(200), nullable=False)
    description = db.Column(db.Text, nullable=True)
    category = db.Column(db.String(50), nullable=True)
    file_path = db.Column(db.String(200), nullable=False)
    file_name = db.Column(db.String(200), nullable=False)
    uploader_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    download_count = db.Column(db.Integer, default=0)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    
    # 关系定义
    collections = db.relationship('ResourceCollection', backref='resource', lazy=True)

class Message(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    sender_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    receiver_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    content = db.Column(db.Text, nullable=False)
    is_read = db.Column(db.Boolean, default=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

class ActivityParticipant(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    activity_id = db.Column(db.Integer, db.ForeignKey('activity.id'), nullable=False)
    registered_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # 唯一约束
    __table_args__ = (db.UniqueConstraint('user_id', 'activity_id', name='_user_activity_uc'),)

class ResourceCollection(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    resource_id = db.Column(db.Integer, db.ForeignKey('resource.id'), nullable=False)
    collected_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # 唯一约束
    __table_args__ = (db.UniqueConstraint('user_id', 'resource_id', name='_user_resource_uc'),)

# 表单定义
class RegistrationForm(FlaskForm):
    username = StringField('用户名', validators=[InputRequired(), Length(min=4, max=20)])
    email = EmailField('邮箱', validators=[InputRequired(), Email()])
    password = PasswordField('密码', validators=[InputRequired(), Length(min=8)])
    confirm_password = PasswordField('确认密码', validators=[InputRequired(), EqualTo('password')])
    submit = SubmitField('注册')
    
    def validate_username(self, username):
        user = User.query.filter_by(username=username.data).first()
        if user:
            raise ValidationError('该用户名已被使用，请选择其他用户名。')
    
    def validate_email(self, email):
        user = User.query.filter_by(email=email.data).first()
        if user:
            raise ValidationError('该邮箱已被注册，请使用其他邮箱。')

class LoginForm(FlaskForm):
    username = StringField('用户名', validators=[InputRequired(), Length(min=4, max=20)])
    password = PasswordField('密码', validators=[InputRequired(), Length(min=8)])
    submit = SubmitField('登录')

class CourseForm(FlaskForm):
    course_code = StringField('课程代码', validators=[InputRequired()])
    name = StringField('课程名称', validators=[InputRequired()])
    instructor = StringField('授课教师')
    credits = StringField('学分')
    day_of_week = SelectField('星期', choices=[
        (0, '周一'), (1, '周二'), (2, '周三'), (3, '周四'), (4, '周五'), (5, '周六'), (6, '周日')
    ], coerce=int, validators=[InputRequired()])
    start_time = TimeField('开始时间', validators=[InputRequired()])
    end_time = TimeField('结束时间', validators=[InputRequired()])
    location = StringField('上课地点')
    semester = StringField('学期', validators=[InputRequired()])
    submit = SubmitField('保存')

class ScoreForm(FlaskForm):
    course_name = StringField('课程名称', validators=[InputRequired()])
    credits = StringField('学分', validators=[InputRequired()])
    score_value = StringField('成绩', validators=[InputRequired()])
    semester = StringField('学期', validators=[InputRequired()])
    submit = SubmitField('保存')

class ActivityForm(FlaskForm):
    title = StringField('活动标题', validators=[InputRequired()])
    description = TextAreaField('活动描述')
    category = StringField('活动类别')
    location = StringField('活动地点')
    start_date = DateField('开始日期', validators=[InputRequired()])
    start_time = TimeField('开始时间', validators=[InputRequired()])
    end_date = DateField('结束日期', validators=[InputRequired()])
    end_time = TimeField('结束时间', validators=[InputRequired()])
    max_participants = StringField('最大参与人数')
    image = FileField('活动图片')
    submit = SubmitField('发布')

class ResourceForm(FlaskForm):
    title = StringField('资源标题', validators=[InputRequired()])
    description = TextAreaField('资源描述')
    category = StringField('资源类别')
    file = FileField('上传文件', validators=[InputRequired()])
    submit = SubmitField('上传')

class MessageForm(FlaskForm):
    content = TextAreaField('消息内容', validators=[InputRequired()])
    submit = SubmitField('发送')

# 用户加载回调
@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

# 认证路由
@app.route('/register', methods=['GET', 'POST'])
def register():
    form = RegistrationForm()
    if form.validate_on_submit():
        hashed_password = generate_password_hash(form.password.data, method='sha256')
        new_user = User(
            username=form.username.data,
            email=form.email.data,
            password=hashed_password
        )
        db.session.add(new_user)
        db.session.commit()
        flash('注册成功！请登录。', 'success')
        return redirect(url_for('login'))
    return render_template('auth/register.html', form=form)

@app.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user and check_password_hash(user.password, form.password.data):
            login_user(user)
            return redirect(url_for('dashboard'))
        flash('用户名或密码错误', 'danger')
    return render_template('auth/login.html', form=form)

@app.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('login'))

# 主页路由
@app.route('/')
@login_required
def dashboard():
    # 获取用户的课程（今天和明天）
    today = datetime.utcnow().date()
    tomorrow = today + timedelta(days=1)
    today_courses = Course.query.filter_by(user_id=current_user.id, day_of_week=today.weekday()).all()
    tomorrow_courses = Course.query.filter_by(user_id=current_user.id, day_of_week=tomorrow.weekday()).all()
    
    # 获取即将开始的活动
    upcoming_activities = Activity.query.filter(Activity.start_time >= datetime.utcnow()).order_by(Activity.start_time).limit(3).all()
    
    # 获取最新资源
    latest_resources = Resource.query.order_by(Resource.created_at.desc()).limit(3).all()
    
    # 获取未读消息数量
    unread_messages_count = Message.query.filter_by(receiver_id=current_user.id, is_read=False).count()
    
    # 计算GPA（如果有成绩）
    gpa = None
    scores = Score.query.filter_by(user_id=current_user.id).all()
    if scores:
        total_credits = sum(float(score.credits) for score in scores)
        weighted_sum = sum(float(score.score_value) * float(score.credits) for score in scores)
        gpa = weighted_sum / total_credits if total_credits > 0 else 0
    
    return render_template('dashboard.html', 
                           today_courses=today_courses, 
                           tomorrow_courses=tomorrow_courses,
                           upcoming_activities=upcoming_activities,
                           latest_resources=latest_resources,
                           unread_messages_count=unread_messages_count,
                           gpa=gpa)

# 课程相关路由
@app.route('/courses')
@login_required
def courses():
    user_courses = Course.query.filter_by(user_id=current_user.id).order_by(Course.day_of_week, Course.start_time).all()
    return render_template('courses/list.html', courses=user_courses)

@app.route('/courses/add', methods=['GET', 'POST'])
@login_required
def add_course():
    form = CourseForm()
    if form.validate_on_submit():
        try:
            credits = float(form.credits.data) if form.credits.data else 0
        except ValueError:
            credits = 0
        
        new_course = Course(
            course_code=form.course_code.data,
            name=form.name.data,
            instructor=form.instructor.data,
            credits=credits,
            day_of_week=form.day_of_week.data,
            start_time=form.start_time.data,
            end_time=form.end_time.data,
            location=form.location.data,
            semester=form.semester.data,
            user_id=current_user.id
        )
        db.session.add(new_course)
        db.session.commit()
        flash('课程添加成功！', 'success')
        return redirect(url_for('courses'))
    return render_template('courses/add.html', form=form)

@app.route('/courses/edit/<int:course_id>', methods=['GET', 'POST'])
@login_required
def edit_course(course_id):
    course = Course.query.get_or_404(course_id)
    if course.user_id != current_user.id:
        flash('您没有权限编辑此课程。', 'danger')
        return redirect(url_for('courses'))
    
    form = CourseForm(obj=course)
    if form.validate_on_submit():
        try:
            credits = float(form.credits.data) if form.credits.data else 0
        except ValueError:
            credits = 0
        
        course.course_code = form.course_code.data
        course.name = form.name.data
        course.instructor = form.instructor.data
        course.credits = credits
        course.day_of_week = form.day_of_week.data
        course.start_time = form.start_time.data
        course.end_time = form.end_time.data
        course.location = form.location.data
        course.semester = form.semester.data
        
        db.session.commit()
        flash('课程更新成功！', 'success')
        return redirect(url_for('courses'))
    return render_template('courses/edit.html', form=form, course=course)

@app.route('/courses/delete/<int:course_id>', methods=['POST'])
@login_required
def delete_course(course_id):
    course = Course.query.get_or_404(course_id)
    if course.user_id != current_user.id:
        flash('您没有权限删除此课程。', 'danger')
        return redirect(url_for('courses'))
    
    db.session.delete(course)
    db.session.commit()
    flash('课程删除成功！', 'success')
    return redirect(url_for('courses'))

@app.route('/courses/schedule')
@login_required
def course_schedule():
    user_courses = Course.query.filter_by(user_id=current_user.id).order_by(Course.day_of_week, Course.start_time).all()
    # 按星期分组课程
    schedule = {i: [] for i in range(7)}
    for course in user_courses:
        schedule[course.day_of_week].append(course)
    
    return render_template('courses/schedule.html', schedule=schedule)

# 成绩相关路由
@app.route('/scores')
@login_required
def scores():
    user_scores = Score.query.filter_by(user_id=current_user.id).order_by(Score.semester).all()
    # 计算GPA
    total_credits = sum(float(score.credits) for score in user_scores)
    weighted_sum = sum(float(score.score_value) * float(score.credits) for score in user_scores)
    gpa = weighted_sum / total_credits if total_credits > 0 else 0
    
    # 按学期分组
    scores_by_semester = {}
    for score in user_scores:
        if score.semester not in scores_by_semester:
            scores_by_semester[score.semester] = []
        scores_by_semester[score.semester].append(score)
    
    # 计算各学期的GPA
    semester_gpas = {}
    for semester, semester_scores in scores_by_semester.items():
        sem_credits = sum(float(score.credits) for score in semester_scores)
        sem_weighted = sum(float(score.score_value) * float(score.credits) for score in semester_scores)
        semester_gpas[semester] = sem_weighted / sem_credits if sem_credits > 0 else 0
    
    return render_template('scores/list.html', 
                          scores=user_scores, 
                          gpa=gpa, 
                          scores_by_semester=scores_by_semester, 
                          semester_gpas=semester_gpas)

@app.route('/scores/add', methods=['GET', 'POST'])
@login_required
def add_score():
    form = ScoreForm()
    if form.validate_on_submit():
        try:
            credits = float(form.credits.data)
            score_value = float(form.score_value.data)
        except ValueError:
            flash('学分和成绩必须是数字。', 'danger')
            return redirect(url_for('add_score'))
        
        new_score = Score(
            user_id=current_user.id,
            course_name=form.course_name.data,
            credits=credits,
            score_value=score_value,
            semester=form.semester.data
        )
        db.session.add(new_score)
        db.session.commit()
        flash('成绩添加成功！', 'success')
        return redirect(url_for('scores'))
    return render_template('scores/add.html', form=form)

@app.route('/scores/edit/<int:score_id>', methods=['GET', 'POST'])
@login_required
def edit_score(score_id):
    score = Score.query.get_or_404(score_id)
    if score.user_id != current_user.id:
        flash('您没有权限编辑此成绩。', 'danger')
        return redirect(url_for('scores'))
    
    form = ScoreForm(obj=score)
    if form.validate_on_submit():
        try:
            credits = float(form.credits.data)
            score_value = float(form.score_value.data)
        except ValueError:
            flash('学分和成绩必须是数字。', 'danger')
            return redirect(url_for('edit_score'))
        
        score.course_name = form.course_name.data
        score.credits = credits
        score.score_value = score_value
        score.semester = form.semester.data
        
        db.session.commit()
        flash('成绩更新成功！', 'success')
        return redirect(url_for('scores'))
    return render_template('scores/edit.html', form=form, score=score)

@app.route('/scores/delete/<int:score_id>', methods=['POST'])
@login_required
def delete_score(score_id):
    score = Score.query.get_or_404(score_id)
    if score.user_id != current_user.id:
        flash('您没有权限删除此成绩。', 'danger')
        return redirect(url_for('scores'))
    
    db.session.delete(score)
    db.session.commit()
    flash('成绩删除成功！', 'success')
    return redirect(url_for('scores'))

@app.route('/scores/analytics')
@login_required
def score_analytics():
    user_scores = Score.query.filter_by(user_id=current_user.id).order_by(Score.semester).all()
    
    # 准备图表数据
    chart_data = {
        'semesters': [],
        'gpas': [],
        'scores_data': []
    }
    
    # 按学期分组
    scores_by_semester = {}
    for score in user_scores:
        if score.semester not in scores_by_semester:
            scores_by_semester[score.semester] = []
            chart_data['semesters'].append(score.semester)
        scores_by_semester[score.semester].append(score)
    
    # 计算各学期GPA
    for semester in chart_data['semesters']:
        sem_scores = scores_by_semester[semester]
        sem_credits = sum(float(score.credits) for score in sem_scores)
        sem_weighted = sum(float(score.score_value) * float(score.credits) for score in sem_scores)
        sem_gpa = sem_weighted / sem_credits if sem_credits > 0 else 0
        chart_data['gpas'].append(round(sem_gpa, 2))
        
        # 为每个学期准备成绩数据
        for score in sem_scores:
            chart_data['scores_data'].append({
                'semester': semester,
                'course': score.course_name,
                'score': float(score.score_value),
                'credits': float(score.credits)
            })
    
    return render_template('scores/analytics.html', chart_data=chart_data)

# 活动相关路由
@app.route('/activities')
@login_required
def activities():
    upcoming_activities = Activity.query.filter(Activity.start_time >= datetime.utcnow()).order_by(Activity.start_time).all()
    past_activities = Activity.query.filter(Activity.end_time < datetime.utcnow()).order_by(Activity.end_time.desc()).limit(10).all()
    
    # 获取用户已报名的活动ID
    user_participations = ActivityParticipant.query.filter_by(user_id=current_user.id).all()
    user_activity_ids = [p.activity_id for p in user_participations]
    
    return render_template('activities/list.html', 
                          upcoming_activities=upcoming_activities, 
                          past_activities=past_activities,
                          user_activity_ids=user_activity_ids)

@app.route('/activities/add', methods=['GET', 'POST'])
@login_required
def add_activity():
    form = ActivityForm()
    if form.validate_on_submit():
        # 处理图片上传
        image_path = None
        if 'image' in request.files and request.files['image'].filename != '':
            file = request.files['image']
            filename = secure_filename(file.filename)
            # 生成唯一文件名
            unique_filename = f"{datetime.utcnow().strftime('%Y%m%d%H%M%S')}_{filename}"
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], unique_filename))
            image_path = unique_filename
        
        # 合并日期和时间
        start_datetime = datetime.combine(form.start_date.data, form.start_time.data)
        end_datetime = datetime.combine(form.end_date.data, form.end_time.data)
        
        # 处理最大参与人数
        max_participants = None
        if form.max_participants.data:
            try:
                max_participants = int(form.max_participants.data)
            except ValueError:
                pass
        
        new_activity = Activity(
            title=form.title.data,
            description=form.description.data,
            category=form.category.data,
            location=form.location.data,
            start_time=start_datetime,
            end_time=end_datetime,
            organizer_id=current_user.id,
            image=image_path,
            max_participants=max_participants
        )
        db.session.add(new_activity)
        db.session.commit()
        flash('活动发布成功！', 'success')
        return redirect(url_for('activities'))
    return render_template('activities/add.html', form=form)

@app.route('/activities/<int:activity_id>')
@login_required
def view_activity(activity_id):
    activity = Activity.query.get_or_404(activity_id)
    is_participant = ActivityParticipant.query.filter_by(user_id=current_user.id, activity_id=activity_id).first() is not None
    participant_count = ActivityParticipant.query.filter_by(activity_id=activity_id).count()
    
    return render_template('activities/view.html', 
                          activity=activity,
                          is_participant=is_participant,
                          participant_count=participant_count)

@app.route('/activities/join/<int:activity_id>', methods=['POST'])
@login_required
def join_activity(activity_id):
    activity = Activity.query.get_or_404(activity_id)
    
    # 检查是否已经报名
    existing_participation = ActivityParticipant.query.filter_by(
        user_id=current_user.id, 
        activity_id=activity_id
    ).first()
    
    if existing_participation:
        flash('您已经报名了此活动。', 'info')
        return redirect(url_for('view_activity', activity_id=activity_id))
    
    # 检查是否超过最大参与人数
    if activity.max_participants is not None:
        current_participants = ActivityParticipant.query.filter_by(activity_id=activity_id).count()
        if current_participants >= activity.max_participants:
            flash('活动名额已满。', 'danger')
            return redirect(url_for('view_activity', activity_id=activity_id))
    
    # 创建参与记录
    participation = ActivityParticipant(
        user_id=current_user.id,
        activity_id=activity_id
    )
    db.session.add(participation)
    db.session.commit()
    flash('报名成功！', 'success')
    return redirect(url_for('view_activity', activity_id=activity_id))

@app.route('/activities/leave/<int:activity_id>', methods=['POST'])
@login_required
def leave_activity(activity_id):
    participation = ActivityParticipant.query.filter_by(
        user_id=current_user.id, 
        activity_id=activity_id
    ).first()
    
    if not participation:
        flash('您没有报名此活动。', 'info')
        return redirect(url_for('view_activity', activity_id=activity_id))
    
    db.session.delete(participation)
    db.session.commit()
    flash('已取消报名。', 'success')
    return redirect(url_for('view_activity', activity_id=activity_id))

@app.route('/activities/delete/<int:activity_id>', methods=['POST'])
@login_required
def delete_activity(activity_id):
    activity = Activity.query.get_or_404(activity_id)
    
    # 检查是否是组织者
    if activity.organizer_id != current_user.id:
        flash('您没有权限删除此活动。', 'danger')
        return redirect(url_for('activities'))
    
    # 删除所有参与记录
    ActivityParticipant.query.filter_by(activity_id=activity_id).delete()
    
    # 删除活动
    db.session.delete(activity)
    db.session.commit()
    flash('活动已删除。', 'success')
    return redirect(url_for('activities'))

# 资源相关路由
@app.route('/resources')
@login_required
def resources():
    all_resources = Resource.query.order_by(Resource.created_at.desc()).all()
    
    # 获取用户收藏的资源ID
    user_collections = ResourceCollection.query.filter_by(user_id=current_user.id).all()
    user_resource_ids = [c.resource_id for c in user_collections]
    
    # 按类别分组
    categories = {}
    for resource in all_resources:
        if resource.category not in categories:
            categories[resource.category] = []
        categories[resource.category].append(resource)
    
    return render_template('resources/list.html', 
                          resources=all_resources,
                          user_resource_ids=user_resource_ids,
                          categories=categories)

@app.route('/resources/add', methods=['GET', 'POST'])
@login_required
def add_resource():
    form = ResourceForm()
    if form.validate_on_submit():
        # 处理文件上传
        if 'file' in request.files and request.files['file'].filename != '':
            file = request.files['file']
            filename = secure_filename(file.filename)
            # 生成唯一文件名
            unique_filename = f"{datetime.utcnow().strftime('%Y%m%d%H%M%S')}_{filename}"
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], unique_filename))
            
            new_resource = Resource(
                title=form.title.data,
                description=form.description.data,
                category=form.category.data,
                file_path=unique_filename,
                file_name=filename,
                uploader_id=current_user.id
            )
            db.session.add(new_resource)
            db.session.commit()
            flash('资源上传成功！', 'success')
            return redirect(url_for('resources'))
        else:
            flash('请选择要上传的文件。', 'danger')
    return render_template('resources/add.html', form=form)

@app.route('/resources/<int:resource_id>')
@login_required
def view_resource(resource_id):
    resource = Resource.query.get_or_404(resource_id)
    is_collected = ResourceCollection.query.filter_by(user_id=current_user.id, resource_id=resource_id).first() is not None
    
    return render_template('resources/view.html', 
                          resource=resource,
                          is_collected=is_collected)

@app.route('/resources/download/<int:resource_id>')
@login_required
def download_resource(resource_id):
    resource = Resource.query.get_or_404(resource_id)
    
    # 增加下载次数
    resource.download_count += 1
    db.session.commit()
    
    # 获取文件路径
    file_path = os.path.join(app.config['UPLOAD_FOLDER'], resource.file_path)
    
    # 检查文件是否存在
    if not os.path.exists(file_path):
        flash('文件不存在。', 'danger')
        return redirect(url_for('view_resource', resource_id=resource_id))
    
    # 这里应该返回文件下载响应
    # 为了简化，我们只返回一个成功消息
    flash(f'文件 {resource.file_name} 下载成功。', 'success')
    return redirect(url_for('view_resource', resource_id=resource_id))

@app.route('/resources/collect/<int:resource_id>', methods=['POST'])
@login_required
def collect_resource(resource_id):
    # 检查是否已经收藏
    existing_collection = ResourceCollection.query.filter_by(
        user_id=current_user.id, 
        resource_id=resource_id
    ).first()
    
    if existing_collection:
        flash('您已经收藏了此资源。', 'info')
        return redirect(url_for('view_resource', resource_id=resource_id))
    
    # 创建收藏记录
    collection = ResourceCollection(
        user_id=current_user.id,
        resource_id=resource_id
    )
    db.session.add(collection)
    db.session.commit()
    flash('资源收藏成功！', 'success')
    return redirect(url_for('view_resource', resource_id=resource_id))

@app.route('/resources/uncollect/<int:resource_id>', methods=['POST'])
@login_required
def uncollect_resource(resource_id):
    collection = ResourceCollection.query.filter_by(
        user_id=current_user.id, 
        resource_id=resource_id
    ).first()
    
    if not collection:
        flash('您没有收藏此资源。', 'info')
        return redirect(url_for('view_resource', resource_id=resource_id))
    
    db.session.delete(collection)
    db.session.commit()
    flash('已取消收藏。', 'success')
    return redirect(url_for('view_resource', resource_id=resource_id))

@app.route('/resources/delete/<int:resource_id>', methods=['POST'])
@login_required
def delete_resource(resource_id):
    resource = Resource.query.get_or_404(resource_id)
    
    # 检查是否是上传者
    if resource.uploader_id != current_user.id:
        flash('您没有权限删除此资源。', 'danger')
        return redirect(url_for('resources'))
    
    # 删除所有收藏记录
    ResourceCollection.query.filter_by(resource_id=resource_id).delete()
    
    # 删除文件
    file_path = os.path.join(app.config['UPLOAD_FOLDER'], resource.file_path)
    if os.path.exists(file_path):
        try:
            os.remove(file_path)
        except Exception as e:
            flash('文件删除失败，但资源记录已删除。', 'warning')
    
    # 删除资源
    db.session.delete(resource)
    db.session.commit()
    flash('资源已删除。', 'success')
    return redirect(url_for('resources'))

@app.route('/resources/collections')
@login_required
def resource_collections():
    user_collections = ResourceCollection.query.filter_by(user_id=current_user.id).order_by(ResourceCollection.collected_at.desc()).all()
    
    return render_template('resources/collections.html', collections=user_collections)

# 社交相关路由
@app.route('/messages')
@login_required
def messages():
    # 获取所有消息（发送和接收）
    all_messages = Message.query.filter(
        (Message.sender_id == current_user.id) | (Message.receiver_id == current_user.id)
    ).order_by(Message.created_at.desc()).all()
    
    # 获取未读消息数量
    unread_count = Message.query.filter_by(receiver_id=current_user.id, is_read=False).count()
    
    # 获取对话用户列表
    conversation_users = {}
    for msg in all_messages:
        other_user_id = msg.sender_id if msg.sender_id != current_user.id else msg.receiver_id
        if other_user_id not in conversation_users:
            user = User.query.get(other_user_id)
            conversation_users[other_user_id] = {
                'user': user,
                'last_message': msg,
                'unread': Message.query.filter_by(
                    sender_id=other_user_id,
                    receiver_id=current_user.id,
                    is_read=False
                ).count()
            }
    
    return render_template('messages/list.html', conversation_users=conversation_users, unread_count=unread_count)

@app.route('/messages/<int:user_id>', methods=['GET', 'POST'])
@login_required
def conversation(user_id):
    other_user = User.query.get_or_404(user_id)
    form = MessageForm()
    
    if form.validate_on_submit():
        new_message = Message(
            sender_id=current_user.id,
            receiver_id=user_id,
            content=form.content.data
        )
        db.session.add(new_message)
        db.session.commit()
        flash('消息发送成功！', 'success')
        return redirect(url_for('conversation', user_id=user_id))
    
    # 获取对话历史
    messages = Message.query.filter(
        ((Message.sender_id == current_user.id) & (Message.receiver_id == user_id)) |
        ((Message.sender_id == user_id) & (Message.receiver_id == current_user.id))
    ).order_by(Message.created_at).all()
    
    # 标记未读消息为已读
    unread_messages = Message.query.filter_by(sender_id=user_id, receiver_id=current_user.id, is_read=False).all()
    for msg in unread_messages:
        msg.is_read = True
    db.session.commit()
    
    return render_template('messages/conversation.html', other_user=other_user, messages=messages, form=form)

@app.route('/users')
@login_required
def users_list():
    # 获取除当前用户外的所有用户
    all_users = User.query.filter(User.id != current_user.id).all()
    
    return render_template('users/list.html', users=all_users)

@app.route('/users/<int:user_id>')
@login_required
def user_profile(user_id):
    user = User.query.get_or_404(user_id)
    form = MessageForm()
    
    return render_template('users/profile.html', user=user, form=form)

# 个人中心路由
@app.route('/profile')
@login_required
def profile():
    return render_template('profile.html', user=current_user)

@app.route('/settings')
@login_required
def settings():
    return render_template('settings.html', user=current_user)

# API路由
@app.route('/api/courses/today')
@login_required
def api_today_courses():
    today = datetime.utcnow().date().weekday()
    courses = Course.query.filter_by(user_id=current_user.id, day_of_week=today).order_by(Course.start_time).all()
    
    result = []
    for course in courses:
        result.append({
            'id': course.id,
            'name': course.name,
            'course_code': course.course_code,
            'instructor': course.instructor,
            'start_time': course.start_time.strftime('%H:%M'),
            'end_time': course.end_time.strftime('%H:%M'),
            'location': course.location
        })
    
    return jsonify(result)

@app.route('/api/activities/upcoming')
@login_required
def api_upcoming_activities():
    activities = Activity.query.filter(Activity.start_time >= datetime.utcnow()).order_by(Activity.start_time).limit(5).all()
    
    result = []
    for activity in activities:
        # 检查用户是否已报名
        is_participant = ActivityParticipant.query.filter_by(
            user_id=current_user.id, 
            activity_id=activity.id
        ).first() is not None
        
        result.append({
            'id': activity.id,
            'title': activity.title,
            'start_time': activity.start_time.strftime('%Y-%m-%d %H:%M'),
            'location': activity.location,
            'is_participant': is_participant
        })
    
    return jsonify(result)

@app.route('/api/scores/gpa')
@login_required
def api_gpa():
    scores = Score.query.filter_by(user_id=current_user.id).all()
    
    # 计算总GPA
    total_credits = sum(float(score.credits) for score in scores)
    weighted_sum = sum(float(score.score_value) * float(score.credits) for score in scores)
    gpa = weighted_sum / total_credits if total_credits > 0 else 0
    
    # 按学期计算GPA
    semester_gpas = {}
    for score in scores:
        if score.semester not in semester_gpas:
            semester_gpas[score.semester] = {'credits': 0, 'weighted_sum': 0}
        semester_gpas[score.semester]['credits'] += float(score.credits)
        semester_gpas[score.semester]['weighted_sum'] += float(score.score_value) * float(score.credits)
    
    # 计算每个学期的GPA
    for semester in semester_gpas:
        if semester_gpas[semester]['credits'] > 0:
            semester_gpas[semester]['gpa'] = semester_gpas[semester]['weighted_sum'] / semester_gpas[semester]['credits']
        else:
            semester_gpas[semester]['gpa'] = 0
    
    result = {
        'gpa': round(gpa, 2),
        'semester_gpas': semester_gpas
    }
    
    return jsonify(result)

# 应用初始化
if __name__ == '__main__':
    # 创建数据库表
    with app.app_context():
        db.create_all()
    
    # 运行应用
    app.run(debug=True)